#include "virtualcanvasmanager.h"
#include "displaycanvascalculator.h"
#include <QDebug>
#include <QPainter>
#include <QCryptographicHash>
#include <QMutexLocker>
#include <QDateTime>
#include <QFont>
#include <QFontMetrics>
#include <cmath>
// === RenderContext实现 ===
VirtualCanvasManager::RenderContext::RenderContext()
    : pageNumber(0)
    , totalPages(0)
    , targetDpi(300.0)
    , pageSizeMM(DisplayCanvasCalculator::A4_WIDTH_MM, DisplayCanvasCalculator::A4_HEIGHT_MM)
    , enableDecorations(true)
{
}
bool VirtualCanvasManager::RenderContext::isValid() const
{
    return targetDpi > 0 &&
           pageSizeMM.width() > 0 && pageSizeMM.height() > 0 &&
           !content.isNull();
}
QString VirtualCanvasManager::RenderContext::generateIdentifier() const
{
    QCryptographicHash hash(QCryptographicHash::Md5);
    // 添加影响渲染结果的关键参数
    hash.addData(QString("dpi_%1").arg(targetDpi).toUtf8());
    hash.addData(QString("page_%1_%2").arg(pageNumber).arg(totalPages).toUtf8());
    hash.addData(QString("pagesize_%1x%2").arg(pageSizeMM.width()).arg(pageSizeMM.height()).toUtf8());
    hash.addData(QString("decorations_%1").arg(enableDecorations).toUtf8());
    if (!content.isNull()) {
        hash.addData(QString("content_%1x%2").arg(content.width()).arg(content.height()).toUtf8());
        // 可以添加内容的哈希，但为了性能考虑，这里只使用尺寸
    }
    if (!customIdentifier.isEmpty()) {
        hash.addData(customIdentifier.toUtf8());
    }
    return hash.result().toHex();
}
QString VirtualCanvasManager::RenderContext::getDebugInfo() const
{
    QString info;
    QTextStream stream(&info);
    stream << "=== 渲染上下文信息 ===" << Qt::endl;
    stream << QString("页码: %1 / %2").arg(pageNumber).arg(totalPages) << Qt::endl;
    stream << QString("目标DPI: %1").arg(targetDpi) << Qt::endl;
    stream << QString("页面尺寸: %1×%2mm").arg(pageSizeMM.width()).arg(pageSizeMM.height()) << Qt::endl;
    stream << QString("内容尺寸: %1×%2").arg(content.width()).arg(content.height()) << Qt::endl;
    stream << QString("启用装饰: %1").arg(enableDecorations ? "是" : "否") << Qt::endl;
    stream << QString("自定义标识: %1").arg(customIdentifier.isEmpty() ? "无" : customIdentifier) << Qt::endl;
    stream << QString("上下文ID: %1").arg(generateIdentifier()) << Qt::endl;
    return info;
}
// === CacheStats实现 ===
VirtualCanvasManager::CacheStats::CacheStats()
    : totalItems(0)
    , totalSizeBytes(0)
    , maxSizeBytes(0)
    , hitCount(0)
    , missCount(0)
    , hitRatio(0.0)
{
}
QString VirtualCanvasManager::CacheStats::toString() const
{
    QString stats;
    QTextStream stream(&stats);
    stream << "=== 虚拟画布缓存统计 ===" << Qt::endl;
    stream << QString("缓存项数: %1").arg(totalItems) << Qt::endl;
    stream << QString("缓存大小: %1 MB / %2 MB").arg(totalSizeBytes / 1024.0 / 1024.0, 0, 'f', 2)
                                                .arg(maxSizeBytes / 1024.0 / 1024.0, 0, 'f', 2) << Qt::endl;
    stream << QString("命中次数: %1").arg(hitCount) << Qt::endl;
    stream << QString("未命中次数: %1").arg(missCount) << Qt::endl;
    stream << QString("命中率: %1%").arg(hitRatio * 100, 0, 'f', 1) << Qt::endl;
    if (!recentKeys.isEmpty()) {
        stream << QString("最近访问: %1").arg(recentKeys.size()) << Qt::endl;
    }
    return stats;
}
// === CacheItem实现 ===
VirtualCanvasManager::CacheItem::CacheItem(const QImage& img, qint64 size)
    : canvas(img)
    , sizeBytes(size)
    , accessCount(1)
{
    qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
    createTime = currentTime;
    lastAccessTime = currentTime;
}
// === VirtualCanvasManager实现 ===
VirtualCanvasManager::VirtualCanvasManager(QObject* parent)
    : QObject(parent)
    , m_maxCacheSizeBytes(DEFAULT_MAX_CACHE_MB * 1024 * 1024)
    , m_currentCacheSizeBytes(0)
    , m_cacheHitCount(0)
    , m_cacheMissCount(0)
    , m_cleanupTimer(new QTimer(this))
    , m_autoCleanupEnabled(true)
    , m_cleanupIntervalMs(DEFAULT_CLEANUP_INTERVAL_MS)
{
    // 设置自动清理定时器
    m_cleanupTimer->setSingleShot(false);
    m_cleanupTimer->setInterval(m_cleanupIntervalMs);
    connect(m_cleanupTimer, &QTimer::timeout, this, &VirtualCanvasManager::performAutoCleanup);
    if (m_autoCleanupEnabled) {
        m_cleanupTimer->start();
    }
}
VirtualCanvasManager::~VirtualCanvasManager()
{
    clearCache();
}
QImage VirtualCanvasManager::getOrCreateVirtualCanvas(const RenderContext& context)
{
    if (!context.isValid()) {
        return QImage();
    }
    QString cacheKey = generateCacheKey(context);
    // 尝试从缓存获取
    QImage cachedCanvas = getCachedCanvas(cacheKey);
    if (!cachedCanvas.isNull()) {
        updateCacheStats(cacheKey, true); // 命中
        emit cacheHit(context.generateIdentifier());
        return cachedCanvas;
    }
    // 缓存未命中，创建新画布
    updateCacheStats(cacheKey, false); // 未命中
    emit cacheMiss(context.generateIdentifier());
    QElapsedTimer timer;
    timer.start();
    QImage newCanvas = doCreateVirtualCanvas(context);
    qint64 createTime = timer.elapsed();
    if (!newCanvas.isNull()) {
        setCachedCanvas(cacheKey, newCanvas);
        emit canvasCreated(context, newCanvas, createTime);
    }
    return newCanvas;
}
QImage VirtualCanvasManager::createVirtualCanvas(const RenderContext& context)
{
    if (!context.isValid()) {
        return QImage();
    }
    QElapsedTimer timer;
    timer.start();
    QImage newCanvas = doCreateVirtualCanvas(context);
    qint64 createTime = timer.elapsed();
    if (!newCanvas.isNull()) {
        emit canvasCreated(context, newCanvas, createTime);
    }
    return newCanvas;
}
void VirtualCanvasManager::preCreateVirtualCanvas(const RenderContext& context)
{
    // 异步预创建（这里简化为直接调用，实际可以使用QFuture等异步机制）
    QString cacheKey = generateCacheKey(context);
    if (!hasCacheKey(cacheKey)) {
        QImage canvas = doCreateVirtualCanvas(context);
        if (!canvas.isNull()) {
            setCachedCanvas(cacheKey, canvas);
        }
    }
}
void VirtualCanvasManager::clearCache()
{
    QMutexLocker locker(&m_cacheMutex);
    int clearedCount = m_cache.size();
    qint64 freedBytes = m_currentCacheSizeBytes;
    m_cache.clear();
    m_currentCacheSizeBytes = 0;
    m_recentAccessKeys.clear();
    emit cacheCleanupCompleted(clearedCount, freedBytes);
    emit cacheUpdated(0, m_maxCacheSizeBytes);
}
void VirtualCanvasManager::clearCacheForDpi(double dpi)
{
    QMutexLocker locker(&m_cacheMutex);
    QString dpiPrefix = QString("dpi_%1_").arg(dpi);
    QStringList keysToRemove;
    for (auto it = m_cache.begin(); it != m_cache.end(); ++it) {
        if (it.key().contains(dpiPrefix)) {
            keysToRemove.append(it.key());
        }
    }
    qint64 freedBytes = 0;
    for (const QString& key : keysToRemove) {
        auto it = m_cache.find(key);
        if (it != m_cache.end()) {
            freedBytes += it->sizeBytes;
            m_currentCacheSizeBytes -= it->sizeBytes;
            m_cache.erase(it);
        }
    }
    // 更新最近访问列表
    for (const QString& key : keysToRemove) {
        m_recentAccessKeys.removeAll(key);
    }
    if (keysToRemove.size() > 0) {
        emit cacheCleanupCompleted(keysToRemove.size(), freedBytes);
        emit cacheUpdated(m_currentCacheSizeBytes, m_maxCacheSizeBytes);
    }
}
void VirtualCanvasManager::clearCacheForPage(int pageNumber)
{
    QMutexLocker locker(&m_cacheMutex);
    QString pagePrefix = QString("page_%1_").arg(pageNumber);
    QStringList keysToRemove;
    for (auto it = m_cache.begin(); it != m_cache.end(); ++it) {
        if (it.key().contains(pagePrefix)) {
            keysToRemove.append(it.key());
        }
    }
    qint64 freedBytes = 0;
    for (const QString& key : keysToRemove) {
        auto it = m_cache.find(key);
        if (it != m_cache.end()) {
            freedBytes += it->sizeBytes;
            m_currentCacheSizeBytes -= it->sizeBytes;
            m_cache.erase(it);
        }
    }
    // 更新最近访问列表
    for (const QString& key : keysToRemove) {
        m_recentAccessKeys.removeAll(key);
    }
    if (keysToRemove.size() > 0) {
        emit cacheCleanupCompleted(keysToRemove.size(), freedBytes);
        emit cacheUpdated(m_currentCacheSizeBytes, m_maxCacheSizeBytes);
    }
}
void VirtualCanvasManager::clearExpiredCache(qint64 maxAgeMs)
{
    QMutexLocker locker(&m_cacheMutex);
    qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
    QStringList keysToRemove;
    for (auto it = m_cache.begin(); it != m_cache.end(); ++it) {
        if (currentTime - it->lastAccessTime > maxAgeMs) {
            keysToRemove.append(it.key());
        }
    }
    qint64 freedBytes = 0;
    for (const QString& key : keysToRemove) {
        auto it = m_cache.find(key);
        if (it != m_cache.end()) {
            freedBytes += it->sizeBytes;
            m_currentCacheSizeBytes -= it->sizeBytes;
            m_cache.erase(it);
        }
    }
    // 更新最近访问列表
    for (const QString& key : keysToRemove) {
        m_recentAccessKeys.removeAll(key);
    }
    if (keysToRemove.size() > 0) {
        emit cacheCleanupCompleted(keysToRemove.size(), freedBytes);
        emit cacheUpdated(m_currentCacheSizeBytes, m_maxCacheSizeBytes);
    }
}
void VirtualCanvasManager::setMaxCacheSize(qint64 maxSizeMB)
{
    if (maxSizeMB <= 0) {
        return;
    }
    QMutexLocker locker(&m_cacheMutex);
    qint64 newMaxSize = maxSizeMB * 1024 * 1024;
    qint64 oldMaxSize = m_maxCacheSizeBytes;
    m_maxCacheSizeBytes = newMaxSize;
    // 如果新限制更小，执行清理
    if (newMaxSize < oldMaxSize && m_currentCacheSizeBytes > newMaxSize) {
        performLRUCleanup(newMaxSize);
    }
    emit cacheUpdated(m_currentCacheSizeBytes, m_maxCacheSizeBytes);
}
qint64 VirtualCanvasManager::getMaxCacheSize() const
{
    return m_maxCacheSizeBytes / 1024 / 1024; // 返回MB
}
void VirtualCanvasManager::setCacheCleanupPolicy(bool enableAutoCleanup, int cleanupIntervalMs)
{
    m_autoCleanupEnabled = enableAutoCleanup;
    m_cleanupIntervalMs = cleanupIntervalMs;
    if (m_autoCleanupEnabled) {
        m_cleanupTimer->setInterval(m_cleanupIntervalMs);
        if (!m_cleanupTimer->isActive()) {
            m_cleanupTimer->start();
        }
    } else {
        m_cleanupTimer->stop();
    }
}
qint64 VirtualCanvasManager::getCurrentCacheSize() const
{
    QMutexLocker locker(&m_cacheMutex);
    return m_currentCacheSizeBytes;
}
VirtualCanvasManager::CacheStats VirtualCanvasManager::getCacheStats() const
{
    QMutexLocker locker(&m_cacheMutex);
    CacheStats stats;
    stats.totalItems = m_cache.size();
    stats.totalSizeBytes = m_currentCacheSizeBytes;
    stats.maxSizeBytes = m_maxCacheSizeBytes;
    stats.hitCount = m_cacheHitCount;
    stats.missCount = m_cacheMissCount;
    int totalAccess = m_cacheHitCount + m_cacheMissCount;
    stats.hitRatio = totalAccess > 0 ? static_cast<double>(m_cacheHitCount) / totalAccess : 0.0;
    stats.recentKeys = m_recentAccessKeys;
    return stats;
}
double VirtualCanvasManager::getCacheUsageRatio() const
{
    QMutexLocker locker(&m_cacheMutex);
    return m_maxCacheSizeBytes > 0 ?
           static_cast<double>(m_currentCacheSizeBytes) / m_maxCacheSizeBytes : 0.0;
}
bool VirtualCanvasManager::hasCachedCanvas(const RenderContext& context) const
{
    QString cacheKey = generateCacheKey(context);
    return hasCacheKey(cacheKey);
}
// === 私有方法实现 ===
QImage VirtualCanvasManager::doCreateVirtualCanvas(const RenderContext& context)
{
    QSize canvasSize = calculateVirtualCanvasSize(context);
    if (canvasSize.isEmpty()) {
        return QImage();
    }
    // 检查画布尺寸是否过大
    qint64 estimatedSize = canvasSize.width() * canvasSize.height() * 4; // ARGB32
    if (estimatedSize > 100 * 1024 * 1024) { // 100MB限制
        return QImage();
    }
    QImage canvas(canvasSize, QImage::Format_ARGB32_Premultiplied);
    canvas.fill(Qt::white); // A4白色背景
    QPainter painter(&canvas);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
    painter.setRenderHint(QPainter::TextAntialiasing, true);
    // 渲染页面内容
    renderPageContent(painter, canvasSize, context);
    // 渲染页面装饰（如果启用）
    if (context.enableDecorations) {
        renderPageDecorations(painter, canvasSize, context);
    }
    painter.end();
    return canvas;
}
QSize VirtualCanvasManager::calculateVirtualCanvasSize(const RenderContext& context) const
{
    // 根据目标DPI和页面物理尺寸计算画布尺寸
    double widthPixels = (context.pageSizeMM.width() / DisplayCanvasCalculator::MM_PER_INCH) * context.targetDpi;
    double heightPixels = (context.pageSizeMM.height() / DisplayCanvasCalculator::MM_PER_INCH) * context.targetDpi;
    return QSize(qRound(widthPixels), qRound(heightPixels));
}
void VirtualCanvasManager::renderPageContent(QPainter& painter, const QSize& canvasSize,
                                           const RenderContext& context)
{
    if (context.content.isNull()) {
        return;
    }
    // 计算内容在画布中的位置
    QRect contentRect = calculateContentRect(context.content.size(), canvasSize, context);
    // 绘制内容
    painter.drawImage(contentRect, context.content);
}
void VirtualCanvasManager::renderPageDecorations(QPainter& painter, const QSize& canvasSize,
                                                const RenderContext& context)
{
    // 设置页码字体（相对于画布大小和DPI）
    QFont font = painter.font();
    int fontSize = qMax(8, qRound(canvasSize.height() * context.targetDpi / 300.0 / 100)); // 基于DPI调整
    font.setPointSize(fontSize);
    painter.setFont(font);
    // 绘制页码（右下角）
    if (context.pageNumber > 0) {
        QString pageText = QString("%1").arg(context.pageNumber);
        if (context.totalPages > 0) {
            pageText = QString("%1 / %2").arg(context.pageNumber).arg(context.totalPages);
        }
        // 计算页码区域（相对于画布大小）
        int margin = qMax(10, canvasSize.width() / 100); // 画布宽度的1%作为边距
        QRect pageNumRect(canvasSize.width() - 150 - margin,
                         canvasSize.height() - 50 - margin,
                         150, 40);
        painter.setPen(Qt::black);
        painter.drawText(pageNumRect, Qt::AlignRight | Qt::AlignBottom, pageText);
    }
    // 可以在这里添加其他装饰：页眉、边框、水印等
    // 例如：绘制页面边框
    QPen borderPen(Qt::lightGray, 1, Qt::SolidLine);
    painter.setPen(borderPen);
    painter.drawRect(0, 0, canvasSize.width() - 1, canvasSize.height() - 1);
}
QRect VirtualCanvasManager::calculateContentRect(const QSize& contentSize, const QSize& canvasSize,
                                                const RenderContext& context) const
{
    Q_UNUSED(context); // 目前未使用，为将来扩展保留
    if (contentSize.isEmpty() || canvasSize.isEmpty()) {
        return QRect();
    }
    // 计算保持宽高比的内容区域
    double contentRatio = static_cast<double>(contentSize.width()) / contentSize.height();
    double canvasRatio = static_cast<double>(canvasSize.width()) / canvasSize.height();
    QSize scaledSize;
    if (contentRatio > canvasRatio) {
        // 内容更宽，以宽度为准
        scaledSize.setWidth(canvasSize.width());
        scaledSize.setHeight(qRound(canvasSize.width() / contentRatio));
    } else {
        // 内容更高，以高度为准
        scaledSize.setHeight(canvasSize.height());
        scaledSize.setWidth(qRound(canvasSize.height() * contentRatio));
    }
    // 居中放置
    QPoint topLeft(
        (canvasSize.width() - scaledSize.width()) / 2,
        (canvasSize.height() - scaledSize.height()) / 2
    );
    return QRect(topLeft, scaledSize);
}
QString VirtualCanvasManager::generateCacheKey(const RenderContext& context) const
{
    return context.generateIdentifier(); // 使用上下文的标识符作为缓存键
}
bool VirtualCanvasManager::hasCacheKey(const QString& cacheKey) const
{
    QMutexLocker locker(&m_cacheMutex);
    return m_cache.contains(cacheKey);
}
QImage VirtualCanvasManager::getCachedCanvas(const QString& cacheKey) const
{
    QMutexLocker locker(&m_cacheMutex);
    auto it = m_cache.find(cacheKey);
    if (it != m_cache.end()) {
        // 使用const_cast修改缓存项的访问统计（这是安全的，因为只修改统计信息，不影响缓存键）
        const_cast<CacheItem&>(it.value()).lastAccessTime = QDateTime::currentMSecsSinceEpoch();
        const_cast<CacheItem&>(it.value()).accessCount++;
        // 更新最近访问列表（mutable成员）
        const_cast<QStringList&>(m_recentAccessKeys).removeAll(cacheKey);
        const_cast<QStringList&>(m_recentAccessKeys).prepend(cacheKey);
        if (m_recentAccessKeys.size() > MAX_RECENT_KEYS) {
            const_cast<QStringList&>(m_recentAccessKeys).removeLast();
        }
        return it->canvas;
    }
    return QImage();
}
void VirtualCanvasManager::setCachedCanvas(const QString& cacheKey, const QImage& canvas)
{
    if (canvas.isNull()) {
        return;
    }
    QMutexLocker locker(&m_cacheMutex);
    qint64 imageSize = calculateImageSize(canvas);
    // 检查是否需要清理缓存
    if (m_currentCacheSizeBytes + imageSize > m_maxCacheSizeBytes) {
        performLRUCleanup(m_maxCacheSizeBytes - imageSize);
    }
    // 如果键已存在，先移除旧的
    auto existingIt = m_cache.find(cacheKey);
    if (existingIt != m_cache.end()) {
        m_currentCacheSizeBytes -= existingIt->sizeBytes;
        m_cache.erase(existingIt);
    }
    // 添加新的缓存项
    CacheItem item(canvas, imageSize);
    m_cache.insert(cacheKey, item);
    m_currentCacheSizeBytes += imageSize;
    // 更新最近访问列表
    m_recentAccessKeys.removeAll(cacheKey);
    m_recentAccessKeys.prepend(cacheKey);
    if (m_recentAccessKeys.size() > MAX_RECENT_KEYS) {
        m_recentAccessKeys.removeLast();
    }
    emit cacheUpdated(m_currentCacheSizeBytes, m_maxCacheSizeBytes);
}
void VirtualCanvasManager::updateCacheStats(const QString& cacheKey, bool isHit)
{
    Q_UNUSED(cacheKey); // 目前只统计总数，不统计具体键
    if (isHit) {
        m_cacheHitCount++;
    } else {
        m_cacheMissCount++;
    }
}
qint64 VirtualCanvasManager::calculateImageSize(const QImage& image) const
{
    return image.sizeInBytes();
}
int VirtualCanvasManager::performLRUCleanup(qint64 targetSize)
{
    if (m_currentCacheSizeBytes <= targetSize) {
        return 0; // 无需清理
    }
    // 按最后访问时间排序，删除最老的项目
    QList<QPair<qint64, QString>> itemsByAccessTime;
    for (auto it = m_cache.begin(); it != m_cache.end(); ++it) {
        itemsByAccessTime.append(qMakePair(it->lastAccessTime, it.key()));
    }
    // 按访问时间升序排序（最老的在前）
    std::sort(itemsByAccessTime.begin(), itemsByAccessTime.end());
    int clearedCount = 0;
    qint64 freedBytes = 0;
    for (const auto& pair : itemsByAccessTime) {
        if (m_currentCacheSizeBytes <= targetSize) {
            break; // 已达到目标大小
        }
        const QString& key = pair.second;
        auto it = m_cache.find(key);
        if (it != m_cache.end()) {
            freedBytes += it->sizeBytes;
            m_currentCacheSizeBytes -= it->sizeBytes;
            m_cache.erase(it);
            clearedCount++;
            // 从最近访问列表中移除
            m_recentAccessKeys.removeAll(key);
        }
    }
    if (clearedCount > 0) {
        emit cacheCleanupCompleted(clearedCount, freedBytes);
        emit cacheUpdated(m_currentCacheSizeBytes, m_maxCacheSizeBytes);
    }
    return clearedCount;
}
void VirtualCanvasManager::performAutoCleanup()
{
    // 清除过期缓存
    clearExpiredCache(CACHE_EXPIRED_MS);
    // 如果缓存使用率过高，执行LRU清理
    double usageRatio = getCacheUsageRatio();
    if (usageRatio > 0.9) { // 使用率超过90%
        qint64 targetSize = qRound(m_maxCacheSizeBytes * 0.8); // 清理到80%
        performLRUCleanup(targetSize);
    }
}